import { nextTick, reactive, ref, unref, UnwrapRef, watch } from 'vue'
import { FormSchema } from '@/components/Form'
import { Table, TableColumn, TableExpose } from '@/components/Table'
import { ElMessage, ElMessageBox, ElTable } from 'element-plus'
import { SUCCESS_CODE } from '@/constants'
import { v4 } from 'uuid'
import { BaseDeleteQo, BasePageQo } from '@/base/api/BaseQo'
import { BaseListVo } from '@/base/api/BaseVo'
import { TableSortProps } from '@/components/Table/src/types'
import { useEventBus } from '@/hooks/event/useEventBus'
import { useRoute } from 'vue-router'

export const useBasePageView = <ListType extends BaseListVo, SearchBoType extends BasePageQo>(
  className: string
) => {
  const pageInfo = reactive({
    pageNum: 1,
    pageSize: 10,
    totalCount: 0,
    totalPage: 0,
    currentPage: 1
  })
  const loading = ref(false)
  const delLoading = ref(false)
  const eventBus = useEventBus()
  const route = useRoute()

  // Table实例
  const tableRef = ref<typeof Table & TableExpose>()

  // ElTable实例
  const elTableRef = ref<ComponentRef<typeof ElTable>>()

  const tableRegister = (ref: typeof Table & TableExpose, elRef: ComponentRef<typeof ElTable>) => {
    tableRef.value = ref
    elTableRef.value = unref(elRef)
  }

  // 获取列表 开始
  const searchParams = ref<SearchBoType>({
    pageNum: 1,
    pageSize: 10
  } as SearchBoType)
  const dataList = reactive<ListType[]>([])

  const baseGetList = async (
    params: any,
    pageApi: (data: BasePageQo) => Promise<IResponse<Array<ListType>>>
  ) => {
    if (!params) {
      params = {}
    }
    loading.value = true
    searchParams.value = params
    searchParams.value['pageNum'] = pageInfo.currentPage
    searchParams.value['pageSize'] = pageInfo.pageSize

    try {
      const res = await pageApi(searchParams.value)
      dataList.splice(0, dataList.length)
      const resDataList = res.data
      if (Array.isArray(resDataList)) {
        resDataList.forEach((item) => {
          dataList.push(item as UnwrapRef<ListType>)
        })
      }
      if (res.page) {
        pageInfo.totalCount = res.page.totalCount
      } else {
        pageInfo.totalCount = 0
      }
    } catch (err) {
      console.error(err)
    } finally {
      loading.value = false
    }
  }

  const doWatch = (getListFunction: (params: any) => void) => {
    watch(
      () => pageInfo.currentPage,
      () => {
        getListFunction(searchParams.value)
      }
    )

    watch(
      () => pageInfo.pageSize,
      () => {
        // 当前页不为1时，修改页数后会导致多次调用getList方法
        if (pageInfo.currentPage === 1) {
          getListFunction(searchParams.value)
        } else {
          pageInfo.currentPage = 1
          getListFunction(searchParams.value)
        }
      }
    )
  }
  // 获取列表 结束

  // 删除数据 开始
  const ids = ref<number[]>([])

  const delData = async (
    row: ListType | null,
    delApi: (deleteBo: BaseDeleteQo) => Promise<IResponse<void>>,
    onDeleteFinish: () => void
  ) => {
    const elTableExpose = await getElTableExpose()
    ids.value = row ? [row.id] : elTableExpose?.getSelectionRows().map((v: ListType) => v.id) || []
    if (!ids.value.length) {
      ElMessage.error('没有选择任何数据')
      return
    }
    delLoading.value = true
    await delList(unref(ids).length, delApi, onDeleteFinish)
  }

  const getTable = async () => {
    await nextTick()
    const table = unref(tableRef)
    if (!table) {
      console.error('The table is not registered. Please use the register method to register')
    }
    return table
  }
  /**
   * @description 获取ElTable组件的实例
   * @returns ElTable instance
   */
  const getElTableExpose = async () => {
    await getTable()
    return unref(elTableRef)
  }

  const delList = async (
    idsLength: number,
    delApi: (deleteBo: BaseDeleteQo) => Promise<IResponse<void>>,
    onDeleteFinish: () => void
  ) => {
    const { pageSize, currentPage, totalCount } = pageInfo
    if (!delApi) {
      console.warn('fetchDelApi is undefined')
      delLoading.value = false
      return
    }
    ElMessageBox.confirm('是否要删除这些数据？', '删除警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(async () => {
        const deleteBo: BaseDeleteQo = {
          ids: unref(ids)
        }
        try {
          const res = await delApi(deleteBo)
          if (res.code === SUCCESS_CODE) {
            ElMessage.success('删除成功')

            // 计算出临界点
            const current =
              unref(totalCount) % unref(pageSize) === idsLength || unref(pageSize) === 1
                ? unref(currentPage) > 1
                  ? unref(currentPage) - 1
                  : unref(currentPage)
                : unref(currentPage)

            pageInfo.currentPage = current
            onDeleteFinish()
          }
        } finally {
          delLoading.value = false
        }
      })
      .catch((_) => {
        delLoading.value = false
      })
  }
  // 删除数据 结束

  // 排序功能 开始
  const baseSortChange = async (
    sortProps: TableSortProps,
    pageApi: (data: BasePageQo) => Promise<IResponse<Array<ListType>>>
  ) => {
    let sortBy = sortProps.column.sortBy
    if (!sortBy) {
      sortBy = sortProps.prop
    }
    if (!sortProps.order) {
      return
    }
    let order = ''
    if (sortProps.order === 'ascending') {
      order = '+'
    } else {
      order = '-'
    }

    searchParams.value['sortBy'] = sortBy
    searchParams.value['sortOrder'] = order
    await baseGetList(searchParams.value, pageApi)
  }
  // 排序功能 结束

  // 导入功能 开始
  const baseInputExcel = async (
    importApi: (formData: FormData) => Promise<IResponse<any>>,
    onImportFinish: () => void
  ) => {
    const fileInput = document.createElement('input')
    fileInput.type = 'file'
    fileInput.accept = '.xlsx'
    fileInput.multiple = true // 允许选择多个文件
    fileInput.onchange = async (event: any) => {
      const files = event.target.files
      if (files.length === 0) return

      let allFilesValid = true
      for (const file of files) {
        if (file.size > 100 * 1024 * 1024) {
          console.error(`文件 ${file.name} 大小超过100MB`)
          alert(`文件 ${file.name} 大小超过100MB`)
          allFilesValid = false
          break
        }
      }

      if (!allFilesValid) return

      const formData = new FormData()
      for (const file of files) {
        formData.append('files', file) // 使用 append 方法逐个添加文件
      }

      console.log('formData', formData)
      try {
        await importApi(formData)
      } catch (error) {
        console.error(`文件上传失败`, error)
        alert(`文件  上传失败`)
      }

      // 刷新列表
      onImportFinish()
    }
    fileInput.click()
  }
  // 导入功能 结束

  // 时间范围快捷搜索 开始
  const datePickerShortcuts = [
    {
      text: '1小时内',
      value: () => {
        const end = new Date()
        const start = new Date()
        start.setTime(start.getTime() - 3600 * 1000)
        return [start, end]
      }
    },
    {
      text: '24小时内',
      value: () => {
        const end = new Date()
        const start = new Date()
        start.setTime(start.getTime() - 3600 * 1000 * 24)
        return [start, end]
      }
    },
    {
      text: '7天内',
      value: () => {
        const end = new Date()
        const start = new Date()
        start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
        return [start, end]
      }
    },
    {
      text: '30天内',
      value: () => {
        const end = new Date()
        const start = new Date()
        start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
        return [start, end]
      }
    },
    {
      text: '近3个月',
      value: () => {
        const end = new Date()
        const start = new Date()
        start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
        return [start, end]
      }
    },
    {
      text: '近1年',
      value: () => {
        const end = new Date()
        const start = new Date()
        start.setTime(start.getTime() - 3600 * 1000 * 24 * 365)
        return [start, end]
      }
    }
  ]
  // 时间范围快捷搜索 结束

  const registerRefreshEvent = (
    pageApi: (data: BasePageQo) => Promise<IResponse<Array<ListType>>>
  ) => {
    eventBus.on('refresh' + className, () => baseGetList({ ...searchParams.value }, pageApi))
  }

  const editUrl = route.fullPath.replace(`${className}Page`, `${className}Edit`)
  const addUrl = route.fullPath.replace(`${className}Page`, `${className}Add`)

  return {
    pageInfo,
    loading,
    delLoading,
    tableRegister,
    ids,
    delData,
    searchParams,
    dataList,
    baseGetList,
    doWatch,
    baseSortChange,
    baseInputExcel,
    datePickerShortcuts,
    registerRefreshEvent,
    editUrl,
    addUrl
  }
}

export interface AllSchemas {
  searchSchema: FormSchema[]
  tableColumns: TableColumn[]
}
